package com.zyb.ext.databasepool;

import com.zyb.ext.databasepool.property.DBBean;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 自定义数据库连接池
 */
@Slf4j
public class MyDatabaseConnPool implements IMyDatabaseConnPool {
    //空闲数据库连接数量
    private List<Connection> idleConnections;
    //活动数据库连接数量
    private List<Connection> activeConnections;
    //真实数据库连接数量
    private AtomicInteger actualConnNum;
    //数据库配置信息
    private DBBean dbBean;

    public MyDatabaseConnPool(DBBean dbBean) {
        this.dbBean = dbBean;
        idleConnections = new Vector<>();
        activeConnections = new Vector<>();
        actualConnNum = new AtomicInteger();
        init();
    }

    /**
     * 初始化数据库连接
     */
    private void init() {
        if (dbBean == null) {
            throw new RuntimeException("数据库配置信息不能为空！");
        }
        if (dbBean.getInitConnNum() > 0) {
            //创建初始化数量的数据库连接
            for (int i = 0; i < dbBean.getInitConnNum(); i++) {
                Connection connection = createConn();
                if (connection != null) {
                    //记录期间创建的数据库连接数量
                    actualConnNum.getAndIncrement();
                    //创建数据库连接
                    idleConnections.add(connection);
                }
            }
        }

    }

    //创建数据库连接
    private Connection createConn() {
        try {
            Class.forName(dbBean.getDriverName());
            return DriverManager.getConnection(dbBean.getUrl(), dbBean.getUserName(), dbBean.getPassword());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    @Override
    public Connection getConnection() {
        Connection connection = null;
        //判断此时存在的数据库连接数是否超过了定义的最大数据库连接数
        if (actualConnNum.get() < dbBean.getMaxActiveConnNum()) {
            //判断数据库的连接来自于哪里
            int status = 0;
            //未超过
            if (idleConnections.size() > 0) {
                connection = idleConnections.remove(0);
                status = 1;
            } else {
                connection = createConn();
                status = 2;
            }
            //验证连接的可用性
            boolean bool = validateConn(connection);
            if (bool) {
                activeConnections.add(connection);
                //如果此连接来自于新创建的，则正是的数据库连接数加1
                if (status == 2) {
                    actualConnNum.getAndIncrement();
                }
            } else {
                //如果此连接是来自于空闲连接的失效连接，则真实的连接数减1
                if (actualConnNum.get() >= 0 && status == 1) {
                    actualConnNum.getAndDecrement();
                }
                connection = null;
                getConnection();
            }
        } else {
            //已超过
            try {
                wait(dbBean.getMaxWaitTime());
            } catch (InterruptedException e) {
                log.error("getConnection >>> wait()方法执行异常！", e);
            }
            getConnection();
        }
        return connection;
    }

    //验证连接的可用性
    private boolean validateConn(Connection connection) {
        boolean flag = true;
        try {
            if (connection == null || connection.isClosed())
                flag = false;
        } catch (SQLException e) {
            log.error("validateConn >>> 验证数据库连接是否可用异常！", e);
            flag = false;
        }
        return flag;
    }

    @Override
    public void destroyConnection(Connection connection) {
        //验证连接是否可用
        if (validateConn(connection)) {
            //验证空闲线程是否满了
            if (idleConnections.size() < dbBean.getMaxIdleConnNum()) {
                //未满,回收连接
                idleConnections.add(connection);
            } else {
                //满了,关闭连接
                try {
                    connection.close();
                } catch (SQLException e) {
                    log.error("destroyConnection >>> 数据库连接关闭异常！", e);
                    return;
                }
                //实际存储的连接数减一
                actualConnNum.getAndDecrement();
            }
            //活动连接数减一
            activeConnections.remove(connection);
        }
    }
}
